home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-screenplay-
/
shareware
/
warpquake
/
warpquakesrc
/
snd_amiga.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-29
|
8KB
|
262 lines
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// snd_amiga.c
#include <exec/exec.h>
#include <dos/dos.h>
#include <graphics/gfxbase.h>
#include <devices/audio.h>
#include <powerpc/powerpc.h>
#include <powerpc/powerpc_protos.h>
extern struct GfxBase *GfxBase;
#include <powerup/ppcproto/exec.h>
#include <powerup/ppcproto/dos.h>
#include <powerup/ppcproto/graphics.h>
#include "quakedef.h"
#define BeginIO(ioRequest) _BeginIO(ioRequest)
__inline void
_BeginIO(struct IORequest *ioRequest)
{
struct PPCArgs args;
memset(&args,0,sizeof(args));
args.PP_Code =(APTR) ioRequest->io_Device;
args.PP_Offset = (-30);
args.PP_Flags = 0;
args.PP_Regs[PPREG_A1] =(ULONG) ioRequest;
args.PP_Regs[PPREG_A6] =(ULONG) ioRequest->io_Device;
Run68K (&args);
}
/**********************************************************************/
extern int desired_speed;
extern int desired_bits;
/**********************************************************************/
#define MAXNUMCHANNELS 4 /* max number of Amiga sound channels */
/* #define BUFFERSIZE 16384 */
#define BUFFERSIZE 4096
struct channel_info {
struct MsgPort *audio_mp;
struct IOAudio *audio_io;
double starttime;
BOOL sound_in_progress;
};
static struct channel_info channel_info[MAXNUMCHANNELS] = {
{NULL, NULL, FALSE},
{NULL, NULL, FALSE},
{NULL, NULL, FALSE},
{NULL, NULL, FALSE},
};
static int size;
static struct MsgPort *audio_mp = NULL;
static struct IOAudio *audio_io = NULL;
static BOOL audio_is_open = FALSE;
static ULONG clock_constant; /* see Amiga Hardware Manual page 141 */
static UWORD period;
static double twice_real_speed;
/**********************************************************************/
// Stops a sound channel.
static void stopsound (int cnum)
{
if (!audio_is_open)
return;
if (channel_info[cnum].sound_in_progress) {
AbortIO ((struct IORequest *)channel_info[cnum].audio_io);
WaitPort (channel_info[cnum].audio_mp);
GetMsg (channel_info[cnum].audio_mp);
channel_info[cnum].sound_in_progress = FALSE;
}
}
/**********************************************************************/
// Starts a sound in a particular sound channel.
static int startsound (int cnum, char *buffer, int length)
{
struct channel_info *c;
if (!audio_is_open)
return 1;
stopsound (cnum);
c = &channel_info[cnum];
c->audio_io->ioa_Request.io_Command = CMD_WRITE;
c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
c->audio_io->ioa_Data = buffer;
c->audio_io->ioa_Length = length;
c->audio_io->ioa_Period = period;
c->audio_io->ioa_Volume = 64;
c->audio_io->ioa_Cycles = 0;
BeginIO ((struct IORequest *)c->audio_io);
c->starttime = Sys_FloatTime ();
c->sound_in_progress = TRUE;
return cnum;
}
/**********************************************************************/
qboolean SNDDMA_Init (void)
{
int i;
struct channel_info *c;
UBYTE chans[1];
// printf ("SNDDMA_Init()\n");
if ((shm = (dma_t *)malloc (sizeof(dma_t))) == NULL)
Sys_Error ("malloc() failed");
memset((void*)shm, 0, sizeof(dma_t));
if ((shm->buffer = AllocMem (BUFFERSIZE, MEMF_CHIP | MEMF_CLEAR)) == NULL)
Sys_Error ("Out of CHIP memory for sound");
// memset(shm->buffer, 0x80, BUFFERSIZE);
// printf ("Sound buffer at 0x%08x\n", shm->buffer);
shm->channels = 2;
shm->speed = desired_speed;
shm->samplebits = 8;
shm->samples = BUFFERSIZE / (shm->samplebits / 8);
shm->submission_chunk = 1;
if ((audio_mp = CreateMsgPort ()) == NULL ||
(audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
Sys_Error ("CreateMsgPort() or AllocMem() failed");
chans[0] = (1 << shm->channels) - 1; /* shm->channels Amiga audio channels */
audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
audio_io->ioa_AllocKey = 0;
audio_io->ioa_Data = chans;
audio_io->ioa_Length = sizeof(chans);
if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
Sys_Error ("OpenDevice(\"audio.device\") failed");
audio_is_open = TRUE;
for (i = 0; i < shm->channels; i++) {
c = &channel_info[i];
if ((c->audio_mp = CreateMsgPort ()) == NULL ||
(c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
Sys_Error ("CreateMsgPort() or AllocMem() failed");
*c->audio_io = *audio_io;
c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
}
if ((GfxBase->DisplayFlags & REALLY_PAL) == 0)
clock_constant = 3579545; /* NTSC */
else
clock_constant = 3546895; /* PAL */
period = ((clock_constant << 1) + shm->speed) / ((shm->speed) << 1);
twice_real_speed = 2.0 * ((double)clock_constant) / (double)period;
startsound (0, shm->buffer, BUFFERSIZE >> 1);
startsound (1, shm->buffer + (BUFFERSIZE >> 1), BUFFERSIZE >> 1);
return 1;
}
/**********************************************************************/
int SNDDMA_GetDMAPos (void)
{
if (shm == NULL || shm->buffer == NULL || !channel_info[0].sound_in_progress)
return 0;
shm->samplepos = ((int)((Sys_FloatTime() - channel_info[0].starttime)
* twice_real_speed + 0.5))
& (BUFFERSIZE - 1);
// shm->samplepos = (int)(realtime*shm->speed*shm->channels) & (shm->samples-1);
// if (pos < 0 || pos >= BUFFERSIZE)
// Sys_Error ("pos = %d is out of range\n");
return shm->samplepos;
}
/**********************************************************************/
void SNDDMA_Shutdown (void)
{
int i;
// printf ("SNDDMA_Shutdown()\n");
if (audio_is_open) {
if (shm != NULL) {
for (i = 0; i < shm->channels; i++)
stopsound (i);
audio_io->ioa_Request.io_Unit = (struct Unit *)
((1 << shm->channels) - 1); /* free shm->channels channels */
}
CloseDevice ((struct IORequest *)audio_io);
audio_is_open = FALSE;
}
for (i = 0; i < MAXNUMCHANNELS; i++) {
if (channel_info[i].audio_io != NULL) {
FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
channel_info[i].audio_io = NULL;
}
if (channel_info[i].audio_mp != NULL) {
DeleteMsgPort (channel_info[i].audio_mp);
channel_info[i].audio_mp = NULL;
}
}
if (audio_io != NULL) {
FreeMem (audio_io, sizeof(struct IOAudio));
audio_io = NULL;
}
if (audio_mp != NULL) {
DeleteMsgPort (audio_mp);
audio_mp = NULL;
}
if (shm != NULL) {
if (shm->buffer != NULL) {
FreeMem (shm->buffer, BUFFERSIZE);
shm->buffer = NULL;
}
free ((char *)shm);
shm = NULL;
}
}
void SNDDMA_Submit (void)
{
// printf ("SNDDMA_Submit()\n");
}
/**********************************************************************/